using System;
using System.Drawing;
using CCAI.Office.PowerPoint.TimedText.Captions;
using TimedText;
using TimedText.Styling;
using Extent = TimedText.Styling.Extent;
using Origin = TimedText.Styling.Origin;

namespace CCAI.Office.PowerPoint.TimedText
{
    /// <summary>
    /// Parses style information about a timed text marker.
    /// </summary>
    /// <remarks>
    /// Style information determines the appearance of the marker text.
    /// This class uses the style information defined in XML and creates corresponding 
    /// Style objects.
    /// Styles are defined in the W3C TTAF 1.0 specification.
    /// </remarks>
    internal static class TimedTextStyleParser
    {
        private static readonly TimedTextStyle DefaultStyle = new TimedTextStyle();
        static ColorConverter converter = new ColorConverter();

        internal static bool IsValidAnimationPropertyName(string name)
        {
            bool ret = false;
            switch (name)
            {
                case "backgroundColor":
                    ret = true;
                    break;
                case "color":
                    ret = true;
                    break;
                case "displayAlign":
                    ret = true;
                    break;
                case "display":
                    ret = true;
                    break;
                case "extent":
                    ret = true;
                    break;
                case "fontFamily":
                    ret = true;
                    break;
                case "fontSize":
                    ret = true;
                    break;
                case "fontStyle":
                    ret = true;
                    break;
                case "fontWeight":
                    ret = true;
                    break;
                case "lineHeight":
                    ret = true;
                    break;
                case "opacity":
                    ret = true;
                    break;
                case "origin":
                    ret = true;
                    break;
                case "overflow":
                    ret = true;
                    break;
                case "padding":
                    ret = true;
                    break;
                case "showBackground":
                    ret = true;
                    break;
                case "textAlign":
                    ret = true;
                    break;
                case "visibility":
                    ret = true;
                    break;
                case "wrapOption":
                    ret = true;
                    break;
                case "zIndex":
                    ret = true;
                    break;
            }
            return ret;
        }

        internal static TimedTextStyle MapStyle(TimedTextElementBase styleElement, RegionElement region)
        {
            var style = new TimedTextStyle
                            {
                                Id = styleElement.Id
                            };


            var backgroundColor =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.BackgroundColor.LocalName, region);

            style.BackgroundColor = backgroundColor!=null
                                        ? (Color)converter.ConvertFromString(backgroundColor.ToString())
                                        : DefaultStyle.BackgroundColor;

            var color =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Color.LocalName, region);
            style.Color = color != null
                              ? (Color)converter.ConvertFromString(color.ToString())
                              : DefaultStyle.Color;

            var extent =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Extent.LocalName, region) as
                Extent;
            style.Extent = extent != null
                               ? new CCAI.Office.PowerPoint.TimedText.Captions.Extent
                                     {
                                         Height = new Length
                                                      {
                                                          Unit =
                                                              ConvertEnum<Unit, LengthUnit>(extent.UnitMeasureVertical),
                                                          Value = (float)extent.Height
                                                      },
                                         Width = new Length
                                                     {
                                                         Unit =
                                                             ConvertEnum<Unit, LengthUnit>(extent.UnitMeasureHorizontal),
                                                         Value = (float)extent.Width
                                                     }
                                     }
                               : DefaultStyle.Extent;


            var fontFamily =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.FontFamily.LocalName, region) as
                string;
            style.FontFamily = !fontFamily.IsNullOrWhiteSpace()
                ? !fontFamily.Equals("default") ? new FontFamily(fontFamily) : DefaultStyle.FontFamily
                                   : DefaultStyle.FontFamily;

            object oFontSize = styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.FontSize.LocalName,
                                                             region);
            var fontSize = oFontSize as string;
            if (!fontSize.IsNullOrWhiteSpace())
            {
                var parsedFontSize = new NumberPair(fontSize);
                style.FontSize = new Length
                                     {
                                         Unit = ConvertEnum<Unit, LengthUnit>(parsedFontSize.UnitMeasureHorizontal),
                                         Value = (float)parsedFontSize.First
                                     };
            }

            var fontStyle =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.FontStyle.LocalName, region) as
                FontStyleAttributeValue?;
            style.FontStyle = fontStyle.HasValue &&
                              (fontStyle.Value == FontStyleAttributeValue.Italic ||
                               fontStyle.Value == FontStyleAttributeValue.Oblique ||
                               fontStyle.Value == FontStyleAttributeValue.ReverseOblique)
                                  ? FontStyle.Italic
                                  : DefaultStyle.FontStyle;

            var fontWeight =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.FontWeight.LocalName, region) as
                FontWeightAttributeValue?;
            style.FontWeight = fontWeight.HasValue && fontWeight.Value == FontWeightAttributeValue.Bold
                                   ? FontStyle.Bold
                                   : DefaultStyle.FontWeight;

            var lineHeight =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.LineHeight.LocalName, region) as
                LineHeight;
            style.LineHeight = lineHeight != null && !(lineHeight is NormalHeight)
                                   ? new Length
                                         {
                                             Unit = ConvertEnum<Unit, LengthUnit>(lineHeight.UnitMeasureVertical),
                                             Value = (float)lineHeight.Height
                                         }
                                   : null;

            var opacity =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Opacity.LocalName, region) as
                double?;
            style.Opacity = opacity.HasValue
                                ? opacity.Value
                                : DefaultStyle.Opacity;

            var origin =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Origin.LocalName, region) as
                Origin;
            style.Origin = origin != null
                               ? new CCAI.Office.PowerPoint.TimedText.Captions.Origin
                                     {
                                         Left = new Length
                                                    {
                                                        Unit =
                                                            ConvertEnum<Unit, LengthUnit>(origin.UnitMeasureHorizontal),
                                                        Value = (float)origin.X
                                                    },
                                         Top = new Length
                                                   {
                                                       Unit = ConvertEnum<Unit, LengthUnit>(origin.UnitMeasureVertical),
                                                       Value = (float)origin.Y
                                                   }
                                     }
                               : DefaultStyle.Origin;

            var overflow =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Overflow.LocalName, region) as
                string;
            Overflow parsedOverflow;
            style.Overflow = overflow.EnumTryParse(true, out parsedOverflow)
                                 ? parsedOverflow
                                 : DefaultStyle.Overflow;

            var padding =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Padding.LocalName, region) as
                PaddingThickness;
            style.Padding = padding != null
                                ? new Padding
                                      {
                                          Left = new Length
                                                     {
                                                         Unit = ConvertEnum<Unit, LengthUnit>(padding.WidthStartUnit),
                                                         Value = (float)padding.WidthStart
                                                     },
                                          Right = new Length
                                                      {
                                                          Unit = ConvertEnum<Unit, LengthUnit>(padding.WidthEndUnit),
                                                          Value = (float)padding.WidthEnd
                                                      },
                                          Top = new Length
                                                    {
                                                        Unit = ConvertEnum<Unit, LengthUnit>(padding.WidthBeforeUnit),
                                                        Value = (float)padding.WidthBefore
                                                    },
                                          Bottom = new Length
                                                       {
                                                           Unit = ConvertEnum<Unit, LengthUnit>(padding.WidthAfterUnit),
                                                           Value = (float)padding.WidthAfter
                                                       }
                                      }
                                : DefaultStyle.Padding;

            //var textAlign =
            //    styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.TextAlign.LocalName, region) as
            //    string;
            //TextAlignment parsedTextAlign;
            //if (textAlign == "start") textAlign = "left";
            //else if (textAlign == "end") textAlign = "right";
            //style.TextAlign = textAlign.EnumTryParse(true, out parsedTextAlign)
            //                      ? parsedTextAlign
            //                      : DefaultStyle.TextAlign;

            var displayAlign =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.DisplayAlign.LocalName, region) as
                string;
            DisplayAlign parsedDisplayAlign;
            style.DisplayAlign = displayAlign.EnumTryParse(true, out parsedDisplayAlign)
                                     ? parsedDisplayAlign
                                     : DefaultStyle.DisplayAlign;

            //var visibility =
            //    styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Visibility.LocalName, region) as
            //    string;
            //style.Visibility = !visibility.IsNullOrWhiteSpace() &&
            //                   visibility.Equals("hidden", StringComparison.CurrentCultureIgnoreCase)
            //                       ? Visibility.Collapsed
            //                       : DefaultStyle.Visibility;

            //var display =
            //    styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.Display.LocalName, region) as
            //    string;
            //style.Display = !display.IsNullOrWhiteSpace() &&
            //                display.Equals("none", StringComparison.CurrentCultureIgnoreCase)
            //                    ? Visibility.Collapsed
            //                    : DefaultStyle.Display;

            //var wrapOption =
            //    styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.WrapOption.LocalName, region) as
            //    string;
            //TextWrapping parsedWrapOption;
            //style.WrapOption = wrapOption.EnumTryParse(true, out parsedWrapOption)
            //                       ? parsedWrapOption
            //                       : DefaultStyle.WrapOption;

            var showBackground =
                styleElement.GetComputedStyle(TimedTextVocabulary.Attributes.Styling.ShowBackground.LocalName, region)
                as string;
            ShowBackground parsedShowBackground;
            style.ShowBackground = showBackground.EnumTryParse(true, out parsedShowBackground)
                                       ? parsedShowBackground
                                       : DefaultStyle.ShowBackground;

            object zindex = styleElement.GetComputedStyle("zIndex", null);
            try
            {
                if (zindex is string == false)
                {
                    var tmp = (double)zindex;
                    style.ZIndex = (int)tmp;
                }
                else
                {
                    style.ZIndex = 0;
                }
            }
            catch
            {
                style.ZIndex = 0;
            }

            return style;
        }


        private static TResult ConvertEnum<TSource, TResult>(TSource source)
            where TSource : struct
            where TResult : struct
        {
            TResult result;
            return source.ToString().EnumTryParse(true, out result)
                       ? result
                       : default(TResult);
        }
    }
}